// Version of 22.3.07

package fournitures;

public class Element {

    /* This class represents an element of the finite field F-256.

       You construct an element by sending a byte value between -128
       and 127 to the constructor. Note that -128 represents the zero
       element of the field.

       There are also three constants that represent the first three
       elements of the field and that you can use in order to reduce
       the risk of confusing -128 and 0: zero, one and two.

       You can retrieve the byte used to construct the element with
       the method getByte.

       You can use the element in mathematical operations by calling
       the methods add, subtract, multiply and divide.
    
       Note that this class uses a more advanced technique for
       multiplication than the one presented in the IIS course. The
       technique makes the operations much faster and is based on
       conversion tables between polynomial and exponential
       representations. You will learn more about this in other
       courses. */

    // ------------------------------------------------------------------
    // Static initializer block for the preparation of conversion
    // tables for multiplication. This code is executed when the class
    // is first loaded, and only once. It is unfortunately not
    // possible to make the tables final as the computation takes
    // place in a statement after the declaration instruction.
    
    static {
        int m = 8;
        int poly = 0x1d;
	size = 1 << m;
        computeConversionTables(m, poly);
    }        

    private static int[] p_to_e;
    private static int[] e_to_p;
    private static int size;

    private static void computeConversionTables (int m, int poly) {
        p_to_e = new int[size];
        e_to_p = new int[size];
        p_to_e[1] = 0;
        p_to_e[0] = 0;
        e_to_p[0] = 1;
        for (int i = 1; i < m; i++) {
            e_to_p[i] = 0x01 << i;
            p_to_e[e_to_p[i]] = i;
        }
        for (int i = m; i < size; i++) {
            e_to_p[i] = e_to_p[i-1] << 1;
            if ((e_to_p[i] & size) == size)
                e_to_p[i] = (e_to_p[i] & ~size) ^ poly;
            p_to_e[e_to_p[i]] = i;
        }
        e_to_p[0] = 1;
    }

    // ------------------------------------------------------------------

    // Private static variables used to precompute elements zero, one and two: 

    private static final byte byteZero = -128;
    private static final byte byteOne = -127;
    private static final byte byteTwo = -126;

    // Static variables for the elements zero, one and two:
    
    public static final Element zero = new Element(byteZero);
    public static final Element one = new Element(byteOne);
    public static final Element two = new Element(byteTwo);

    // ------------------------------------------------------------------

    // pol and exp stand for the polynomial and exponential
    // representations of the element. 

    private int pol;   //  polynomial representation
    private int exp;   //  exponential representation

    public Element (byte b) {
        // Constructs an Element in the field F-256 for this byte.
        // Note that -128 represents the zero element when you call
        // this method.
        int i = b + 128;
	this.pol = i;
	this.exp = p_to_e[i];
    }

    public Element (int i) {
        // Constructs an Element in the field F-256 for this integer.
        // This constructor is private and only used internally in the
        // class. Note that the value of i should be in the interval
        // 0..255. If you have a byte, i.e. a value in the interval
        // -128..127, you should call the other constructor.
	this.pol = i;
	this.exp = p_to_e[i];
    }

    public Element add (Element a) {
        // Returns a new element that is the addition of this and a.
        Element g;
        g = new Element(this.pol ^ a.pol);
        return g;
    }

    public Element subtract (Element a) {
        // Returns a new element that is the subtraction of this and
        // a. Note that subtraction is the same as addition over
        // F-256.
        return add(a);
    }

    public Element multiply (Element a) {
        // Returns a new element that is the multiplication of this and a.
        Element g;
	if((this.pol == 0) || (a.pol == 0)) {
            g = zero;
        }
	else
            g = new Element(e_to_p[(this.exp + a.exp) % (size - 1)]);
        return g;
    }

    public Element divide (Element a) {
        // Returns a new element that is the division of this by a.
        Element g;
	if (a.pol == 1) 
            g = this;
      	else
            g = multiply(new Element(e_to_p[size - 1 - a.exp]));
        return g;
    }

    public byte getByte () {
        // Returns the byte that was used to construct this Element.
        // The value will be between -128 and 127.
        int i = pol - 128;
        byte b = (byte)i;
        return b;
    }

    public String toString () {
        String s; 
        s = "<" + pol + ">";
        return s;
    }    

    public boolean equals (Object anObject) {
        // Two elements are equal if they have the same poly variable,
        // i.e. the same byte value.
        Element el = (Element)anObject;
        boolean b = (this.pol == el.pol);
        return b;
    }
}
